#include "Components/ComponentSickness.h"
#include "Components/ComponentPlayer.h"
#include "Components/ComponentHealth.h"
#include "Components/ComponentSleep.h"

#include "Network/Packages/ComponentSicknessPackage.h"
#include "Network/PackageManager.h"
#include "Subsystems/SubsystemTimeOfDay.h"
#include "Subsystems/SubsystemGameInfo.h"
#include "Player/PlayerData.h"

#include "GameSingleton.h"
#include "GameRegistry.hpp"
#include "GameThreadPool.hpp"


namespace PocketSurvival
{
    void ComponentSickness::update(float dt)
    {
        SubsystemGameInfo *gameInfo = GameSingleton::singletonPtr->getSingleton<SubsystemGameInfo>();
        SubsystemTimeOfDay *timeOfDay = GameSingleton::singletonPtr->getSingleton<SubsystemTimeOfDay>();

        if (componentPlayer->playerData->gameMode == GameMode::Creative || 
            gameInfo->areAdventureSurvivalMechanicsEnabled == false)
        {
            sicknessDuration = 0.0f;
            return;
        }
        if(sicknessDuration > 0.0f)
        {
            sicknessDuration = MathUtils::Max<float>(sicknessDuration - dt, 0.0f);

            if(componentPlayer->componentHealth->health > 0.0f && 
               componentPlayer->componentSleep->isSleeping() == false &&
               timeOfDay->periodicGameTimeEvent(3.0f, -1.0f) &&
               (lastNauseaTime == 0.0f || timeOfDay->getGameTime() - lastNauseaTime > 15.0f))
            {
                nauseaEffect();
                GameSingleton::packageManager->addSendPackageToQueue(std::make_shared<ComponentSicknessPackage>(this));
            }
        }
    }


    void ComponentSickness::nauseaEffect()
    {
        lastNauseaTime = GameSingleton::singletonPtr->getSingleton<SubsystemTimeOfDay>()->getGameTime();
        float injure = MathUtils::Min<float>(0.1f, componentPlayer->componentHealth->health - 0.075f);
        if(injure > 0.0f)
        {
            componentPlayer->componentHealth->injure(injure, entt::null, false, "因食物中毒而死", InjureType::FoodPoisoning);
        }
    }
    void ComponentSickness::startSickness()
    {
        sicknessDuration = 900.0f;
    }
    void ComponentSickness::endSickness()
    {
        sicknessDuration = 0.0f;
        GameSingleton::packageManager->addSendPackageToQueue(std::make_shared<ComponentSicknessPackage>(this));
    }

    static const std::string componentName = "Sickness";
	const std::string &ComponentSickness::getName() const
    {
        return componentName;
    }
    const std::string &ComponentSickness::GetName()
    {
        return componentName;
    }
    void ComponentSickness::load(const nlohmann::json &jsonData)
    {
        componentPlayer = GameSingleton::gameRegistry->get<ComponentPlayer*>(entity);
        sicknessDuration = jsonData["SicknessDuration"].get<float>();
    }
    void ComponentSickness::save(nlohmann::json &jsonData)
    {
        jsonData["SicknessDuration"] = sicknessDuration;
    }
    void ComponentSickness::saveToMsgJson(nlohmann::json &jsonData)
    {
        MSG_VALUE_SET(jsonData, "SicknessDuration", "float", sicknessDuration);
    }
    
} // namespace PocketSurvival
